SFML

Die Übersichtlichkeit der Seite wird durch Javascript erhöht. Ist dies aktiviert, werden die Texte unter den Überschriften durch Anklicken der Überschriften ein- und ausgeblendet.

Reference

SFML ist ein Multimediaframework für eine einfache Spiele-Programmierung. Es beinhaltet 5 Module:

system

window

graphics

audio

network

Tutorial

Installation unter Linux

Unter Arch einfach das Paket sfml installieren. So entsprechen die Pfade zu den header-Dateien automatisch dem Standardpfad des Systems. Sollte man sfml an einer anderen Stelle des Systems haben wollen, so muss man beim kompilieren der

Ein Programm mit sfml kompilieren

Standard-Pfad

Wenn man das Paket über die Paketverwaltung des Systems installiert hat, befinden sich die header-Dateien von sfml im Standard-Pfad des Systems.

Kompilieren

Die Datei kan dann einfach durch

g++ -c main.cpp 

kompiliert werden.

nach oben

Linken

Die kompilierte Datei muss danach noch gegen die sfml-Bibliotheken gelinkt werden. SFML besteht aus den 5 Bibliotheken-Modulen:

  • system
  • window
  • graphics
  • network
  • audio

Um die Bibliothek zu verlinken muss man

-lsfml-MODULNAMEN

Um also ein einfaches Fenster mit einer Grafik zu nutzen, muss in der cpp-Datei *<include><SFML/Graphics.hpp>* stehen. und für die Verlinkung

g++ main.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system

angegeben werden.

nach oben

Kompilieren und Linken

Zusammengefasst ist das folgender Befehl:

g++ main.cpp -lsfml-graphics -lsfml-window -lsfml-system -o sfml-app

nach oben

ausführen

Das Programm lässt sich aus dem Programmverzeichnis wie gewohnt starten durch:

./sfml-app

nach oben

Makefile

# *_* Makefile *_*
# Zur Nutzung von sfml

PN=test-main.cpp

C=g++ -c -std=c++14 -Wall 
L=g++ -lsfml-graphics -lsfml-window -lsfml-system

all: main

main: main.o
	$(L) $^ -o $@
	
main.o: $(PN)
	$(C) $^ -o $@
	
clear:
	$(RM) *.o

nach oben

Abweichender Pfad

Kompilieren

Sollte man sfml an einer anderen Stelle des Systems haben, so muss man für das Kompilieren angeben, wo die heder-Dateien von sfml sind:

g++ -c main.cpp -I<sfml-installationspfad>/include

nach oben

Ausführen

Wenn sfml nicht im Standardpfad installiert ist muss man dem dynamischen Linker zum Starten des Programms mitteilen, wo die sfml-Bibliothek liegt, indem man LD_LIBRARY_PATH festlegt.

export LD_LIBRARY_PATH=<sfml-Installationspfad>/lib && ./sfml-app

nach oben

Test

Um die funktionsweise zu testen kann man folgendes Programm wie oben beschrieben erstellen und ausführen:

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
    sf::CircleShape shape(100.f);
    shape.setFillColor(sf::Color::Green);

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(shape);
        window.display();
    }

    return 0;
}

Wenn es funktioniert, öffnet sich ein 200x200 Pixel großes Fenster mit dem Titel SFML Works!" und einem grünen Kreis, in der Größe dieses Fensters (radius = 100 Pixel)

nach oben

Fenster

in Kürze

Window-Klasse

Konstruktor

sf::Window fenster(sf::VideoMode(800,600), "Mein Fenster");           

nach oben

create(VideoMode(X,Y),"Titel")

sf::Window fenster;
fenster.create( sf::VideoMode(200,200), "Test" );                     

nach oben

isOpen()

while (window.isOpen())
{
  // solange das Fenster geöffnet ist
}

nach oben

Event-Klasse / pollEvent(Event) / close();

sf::Event event;
while (window.pollEvent(event))
{
  if (event.type == sf::Event::Closed) window.close();
}

nach oben

Ausführlich

Für die Nutzung von Fenstern gibt es die Window-Klasse im Namespace sf. Ein Fenster kann direkt bei der Konstruktion erstellt und geöffnet werden. Dazu Übergibt man dem Konstruktor den sf::VideoMode( Fensterbreite, Fensterhöhe ) und den Namen des Fensters.

sf::Window fenster(sf::VideoMode(800,600), "Mein Fenster");

Dem Konstruktor kann noch ein 3. optionaler Parameter mitgegeben werden, der die Fensterdekoration bestimmt: (alle Parameter jeweils im Namespace sf)

Parameter Bedeutung
Style::None ohne Dekoration
Style::Titlebar Fenster Kopfzeile
Style::Resize Fenster Größenveränderlich
Style::Close Fenster mit Schließenbutton
Style::Fullscreen Bei entsprechenden Videomodus nur Vollbild
Style::Default Standard: Titlebar , Resize, Close

Soll das Fenster zunächst nur definiert und erst später initialisiert oder später geändert werden, so ist dies über die create-Funktion mit den selben Parametern wie im Konstruktor möglich.

sf::Window fenster;
fenster.create( sf::VideoMode(200,200), "Test" );

Um das Fenster auch nutzen zu können, muss innerhalb einer Schleife die Ereignisbehandlung und die Fenstersteuerung organiert werden:

while (fenster.isOpen()) # solange das Fenster geöffnet ist
{
  // prüfe alle Fensterereignisse seit dem lesten Loop
  sf::Event event;
  while (window.pollEvent(event))
  {
  // Wenn Fenster-Schließen-Ereignis: Fenster schließen
     if (event.type == sf::Event::Closed)
       window.close();
  }
}

nach oben

Fensterfunktionen

Änderung der Festerpostion auf dem Desktop

fenster.setPosition(sf::Vector2i(10, 50));

nach oben

Änderung der Fenstergröße

fenster.setSize(sf::Vector2u(640, 480));

Ermitteln der Fenstergröße

sf::Vector2u size = fenster.getSize();
unsigned int width = size.x;
unsigned int height = size.y;

nach oben

Änderung des Fenstertitels

fenster.setTitle("neuer Titel");

nach oben

Ereignisse

Ereignisse werden immer in einer Ereignisschleiffe abgefragt. Dabei wird die Eventvariable als Parameter der .pollEvent-Methode des Window-Objektes übergeben und muss dann über eventvariable.type auf Ihren Typ geprüft werden.

sf::Event ereignis;
// Solange es Ereignisse gibt
while (window.pollEvent(event))
{
    // prüfe den Typ des Ereignisses
    switch (ereignis.type)
    {
        // Fenster geschlossen
        case sf::Event::Closed:
            fenster.close();
            break;

        // Taste gedrückt
        case sf::Event::KeyPressed:
            ...
            break;

        // we don't process other types of events
        default:
            break;
    }
}

sf::Event::Closed

Dieses Ereignis zeigt eine Schließen-Anfrage an, auf die man dann reagieren kann. Normaler weise damit das Fenster durch fenster.close(); zu schließen.

nach oben

sf::Event::Resized

Rezized zeigt an, dass das Fenster in seiner Größe verändert wird. Die neue Fenstergröße kann abgefragt werden über ereignis.size.width und ereignis.size.heigth.

if (ereignis.type == sf::Event::Resized)
{
    std::cout << "new width: " << ereignis.size.width << std::endl;
    std::cout << "new height: " << ereignis.size.height << std::endl;
}

nach oben

sf::Event::LostFocus / sf::Event::GainedFocus

Die Ereignisse werden ausgelöst, wenn ein Fenster den Fokus verliert bzw. erhält.

if (event.type == sf::Event::LostFocus)
    myGame.pause();

if (event.type == sf::Event::GainedFocus)
    myGame.resume();

nach oben

sf::Event::KeyPressed / sf::Event::KeyReleased

Diese Ereignisse zeigen an, das eine Taste auf der Tastatur gedrückt bzw. losgelassen wurde. Wenn eine Taste gedrückt gehalten wird, werden mehrfache KeyPressed-Ereignisse generiert. Um dieses Verhalten zu deaktivieren, kann man fenster.setkeyRepeatEnabled(false) aufrufen. Dieses Ereignis macht es möglich direkt auf einen Tastendruck zu reagieren. Um etwas zu tun, solange eine Taste gedrückt wurde, kann man bei Tatendruck ein Flag auf true setzten, das beim loslassen, wieder auf False gesetzt wird. Für die Verabeitung von Tastatureingaben sollte allerdings das in der Folge erklärte TextEntered-Ereignis genutzt werden.

Welche Taste gedrückt bzw. losgelassen wurde, kann über die key-Eigenschaft der Ereignisvariable abgeruffen werden, genau wie der Status der Umschalttasten (Alt,STRG,Shift,System).

if (ereignis.type == sf::Event::KeyPressed)
{
    if (ereignis.key.code == sf::Keyboard::Escape)
    {
        std::cout << "the escape key was pressed" << std::endl;
        std::cout << "control:" << ereignis.key.control << std::endl;
        std::cout << "alt:" << ereignis.key.alt << std::endl;
        std::cout << "shift:" << ereignis.key.shift << std::endl;
        std::cout << "system:" << ereignis.key.system << std::endl;
    }
}

nach oben

sf::Event::TextEntered

Dieses Ereignis wird ausgelöst, wenn ein Zeichen eingegeben wird. Das muss nicht mit dem KeyPressed-Ereignis zusammenhängen. Zu diesem Ereignis kommt es immer dann, wenn eine Eingabe als ein Zeichen interpretiert werden kann. So erzeugen die Beiden Tasten '^' und 'e' zwei KeyPressed-Ereignisse, aber nur einen einzelnes TextEntered-Ereignis für das Zeichen 'ê'.

Der Unicode-Wert des eingegebenen Zeichens kann über ereignis.text ausgelesen werden und entweder direkt in einen sf::String eingefügt oder in ein Char gecastet werden, nachdem sichergestellt wurde, dass der Wert im ASCII-Bereich von 0-127 liegt.

if (ereignis.type == sf::Event::TextEntered)
{
    if (ereignis.text.unicode < 128)
        std::cout << "ASCII character typed: " << static_cast<char>(ereignis.text.unicode) << std::endl;
}

nach oben

sf::Event::MouseWheelScrolled

Das Ereignis wird ausgelöst wenn das Mausrad bewegt wird. Über ereignis.mouseWheelScroll läst sich die Zahl der Bewegungen, deren Orientierung und die Position des Mauszeigers abfragen.

if (ereignis.type == sf::Event::MouseWheelScrolled)
{
    if (ereignis.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel)
        std::cout << "wheel type: vertical" << std::endl;
    else if (ereignis.mouseWheelScroll.wheel == sf::Mouse::HorizontalWheel)
        std::cout << "wheel type: horizontal" << std::endl;
    else
        std::cout << "wheel type: unknown" << std::endl;
    std::cout << "wheel movement: " << ereignis.mouseWheelScroll.delta << std::endl;
    std::cout << "mouse x: " << ereignis.mouseWheelScroll.x << std::endl;
    std::cout << "mouse y: " << ereignis.mouseWheelScroll.y << std::endl;
}

nach oben

sf::Event::MouseButtonPressed / sf::Event::MouseButtonReleased

Diese Ereignisse werden ausgelöst wenn ein Mausbutton gedrückt/losgelassen wird. SFML ünterstütz 5 Mausbutton: Left, Right, Middle, extra #1 und extra #2. Über ereignis.maouseButton kann der Code des gedrückten/losgelassenen Buttons und die Mauspusition abgefragt werden.

if (ereignis.type == sf::Event::MouseButtonPressed)
{
    if (ereignis.mouseButton.button == sf::Mouse::Right)
    {
        std::cout << "the right button was pressed" << std::endl;
        std::cout << "mouse x: " << ereignis.mouseButton.x << std::endl;
        std::cout << "mouse y: " << ereignis.mouseButton.y << std::endl;
    }
}

nach oben

sf::Event::MouseMoved

Dieses Ereignis wird ausgelöst, wenn die Maus über das innere des Fensters (Ohne Titelzeile oder Ränder) bewegt wird, auch wenn das Fenster nicht den Focus hat.

Über die mouseMove-Eigenschaft des Ereignisobjektes kann die aktuelle Kursorposition innerhalb des Fensters abgefragt werden.

if (ereignis.type == sf::Event::MouseMoved)
{
    std::cout << "new mouse x: " << ereignis.mouseMove.x << std::endl;
    std::cout << "new mouse y: " << ereignis.mouseMove.y << std::endl;
}

nach oben

sf::Event::MouseEntered / sf::Event::MouseLeft

Diese Ereignisse werden ausgelöst, wenn der Mauszeiger das Programmfenster erreicht oder verlässt.

nach oben